home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / CODECS.ZIP / codecs / english / codrle3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-13  |  9.0 KB  |  231 lines

  1. /* File: codrle3.c
  2.    Author: David Bourgin
  3.    Creation date: 1/2/94
  4.    Last update: 24/7/95
  5.    Purpose: Example of RLE type 3 encoding with a file source to compress.
  6. */
  7.  
  8. #include <stdio.h>
  9. /* For routines printf,fputc,fread,fwrite and rewind */
  10. #include <memory.h>
  11. /* For routines memset,memcpy */
  12. #include <stdlib.h>
  13. /* For routine exit */
  14.  
  15. /* Error codes sent to the caller */
  16. #define NO_ERROR      0
  17. #define BAD_FILE_NAME 1
  18. #define BAD_ARGUMENT  2
  19.  
  20. /* Useful constants */
  21. #define FALSE 0
  22. #define TRUE  1
  23.  
  24. #define MAX_FRAME_SIZE  256
  25.  
  26. /* Global variables */
  27. FILE *source_file,*dest_file;
  28.  
  29. unsigned int index=0,
  30.              buffer_read_size=0;
  31. unsigned char buffer_read[3*256];
  32.  
  33. typedef struct { unsigned int array_size;
  34.                  unsigned char *array_val;
  35.                } t_tab;
  36. #define ARRAY_SIZE(array)  ((array).array_size)
  37. #define ARRAY_VAL(array)  ((array).array_val)
  38. #define ARE_EQUAL(array1,array2)  ((ARRAY_SIZE(array1)==ARRAY_SIZE(array2))&&(!memcmp(ARRAY_VAL(array1),ARRAY_VAL(array2),ARRAY_SIZE(array1))))
  39.  
  40. /* Pseudo procedures */
  41. #define size_remaining_to_read() (buffer_read_size-index)
  42.  
  43. #define read_block()  { if (!size_remaining_to_read())\
  44.                            { buffer_read_size=fread(buffer_read,1,sizeof(buffer_read),source_file);\
  45.                              index=0;\
  46.                            }\
  47.                       }
  48. #define move_index(i)  (index=(i))
  49. #define beginning_of_data()  { (void)rewind(source_file); buffer_read_size=0; index=0; }
  50. #define end_of_data()  (size_remaining_to_read()?FALSE:(index=0,!(buffer_read_size=fread(buffer_read,1,sizeof(buffer_read),source_file))))
  51. #define read_byte()  ((unsigned char)(end_of_data()?EOF:buffer_read[index++]))
  52. #define read_array(array,nb_to_read)  { ARRAY_SIZE(array)=(nb_to_read);\
  53.                                         ARRAY_VAL(array)= &(buffer_read[index]);\
  54.                                         index += (nb_to_read);\
  55.                                       }
  56. #define write_byte(x)  ((void)fputc((unsigned char)(x),dest_file))
  57. #define write_array(array)  ((void)fwrite(ARRAY_VAL(array),1,ARRAY_SIZE(array),dest_file))
  58. #define fill_block()  { (void)memcpy(buffer_read,&(buffer_read[index]),size_remaining_to_read());\
  59.                         buffer_read_size=fread(&(buffer_read[size_remaining_to_read()]),1,sizeof(buffer_read)-size_remaining_to_read(),source_file)+size_remaining_to_read();\
  60.                         index=0;\
  61.                       }
  62.  
  63. void rle3look_for_occurr(frame_nb,frame_size,
  64.                          repetition_ok)
  65. /* Returned parameters: 'frame_nb', 'frame_size' and 'repetition_ok' are modified
  66.    Action: Looks in the byte buffer if there's a frame repetition
  67.    where size and repetition are respectively in 'frame_size' and 'frame_nb'.
  68.    Whenever a repetition is met, 'repetition_ok' returns 'TRUE' otherwise 'repetition_ok' returns 'FALSE'
  69.    Errors: Whenever there are no multiple frames then 'frame_nb' won't be modified
  70.    If there is a repetition such as (frame_nb-1)*frame_size>3 the buffer is
  71.    completed so that it contains only one occurrence of the frame a its beginning.
  72.    (The repetitions have been flushed by caliing 'fill_block').
  73. */
  74. unsigned int *frame_nb,*frame_size;
  75. int *repetition_ok;
  76. { int array_equality;
  77.   t_tab array1,array2;
  78.  
  79.   *frame_size=1;
  80.   *repetition_ok=FALSE;
  81.   while ((*frame_size<=MAX_FRAME_SIZE)&&(size_remaining_to_read()>=(*frame_size << 1))&&(!*repetition_ok))
  82.         { read_array(array1,*frame_size);
  83.           read_array(array2,*frame_size);
  84.           if (array_equality=ARE_EQUAL(array1,array2))
  85.              { *frame_nb=2;
  86.                while ((size_remaining_to_read()>=*frame_size)&&(*frame_nb<=255)&&(array_equality))
  87.                      { if ((*frame_nb-1)*(*frame_size)>3)
  88.                           { if (*repetition_ok)
  89.                                move_index(*frame_size);
  90.                             else { *repetition_ok=TRUE;
  91.                                    move_index((*frame_nb-1)*(*frame_size));
  92.                                  }
  93.                             fill_block();
  94.                             move_index(*frame_size);
  95.                           }
  96.                        read_array(array2,*frame_size);
  97.                        if (array_equality=ARE_EQUAL(array1,array2))
  98.                           (*frame_nb)++;
  99.                      }
  100.                if ((*frame_nb-1)*(*frame_size)>3)
  101.                   { if (*repetition_ok)
  102.                        { if (array_equality)
  103.                             { move_index(*frame_size);
  104.                               fill_block();
  105.                             }
  106.                        }
  107.                     else { *repetition_ok=TRUE;
  108.                            move_index((*frame_nb-1)*(*frame_size));
  109.                            fill_block();
  110.                          }
  111.                     (*frame_size)--;
  112.                   }
  113.                              /* Specify to the caller there was a repetition */
  114.              }
  115.           (*frame_size)++;
  116.           move_index(0);
  117.         }
  118. }
  119.  
  120. void rle3write_non_rep(header_byte,non_repeated_byte)
  121. /* Returned parameters: None
  122.    Action: Writes in the output compression stream the byte 'non_repeated_byte'
  123.    'header_byte' is used as marker as defined in RLE 3 method
  124.    Errors: An input/output error could disturb the running of the program
  125. */
  126. unsigned char header_byte,non_repeated_byte;
  127. { if (non_repeated_byte==header_byte)
  128.      { write_byte(header_byte);
  129.        write_byte(0);
  130.        write_byte(0);
  131.      }
  132.   else write_byte(non_repeated_byte);
  133. }
  134.  
  135. void rle3write_rep(header_byte,frame,repetition)
  136. /* Returned parameters: None
  137.    Action: Writes in the output compression stream 'repetition' times 'frame' which size is given by 'frame_size'
  138.    'header_byte' is used as marker as defined in RLE 3 method
  139.    Errors: An input/output error could disturb the running of the program
  140. */
  141. unsigned char header_byte;
  142. t_tab frame;
  143. unsigned int repetition;
  144. { write_byte(header_byte);
  145.   write_byte(repetition-1);
  146.   write_byte(ARRAY_SIZE(frame)-1);
  147.   write_array(frame);
  148. }
  149.  
  150. void rle3encoding()
  151. /* Returned parameters: None
  152.    Action: Compresses with RLE type 3 method all bytes read by the function 'read_byte'
  153.    Errors: An input/output error could disturb the running of the program
  154. */
  155. { register unsigned int i;
  156.   unsigned long int occurrence_table[256];
  157.   unsigned char header_byte;
  158.   t_tab frame;
  159.   unsigned int frame_nb,frame_size;
  160.   int repetition_valid;
  161.  
  162.   if (!end_of_data())        /* Is there at least a byte to analyze? */
  163.      {                       /* Sets up the occurrence numbers of all bytes to 0 */
  164.        (void)memset((char *)occurrence_table,0,sizeof(occurrence_table));
  165.                              /* This is the same to fill 'occurrence_table' to 0.
  166.                                 It's fastest than to loop 256 times */
  167.        while (!end_of_data())/* Valids the occurrences in 'occurrence_table' in regard to the data to compress */
  168.  
  169.              { header_byte=read_byte();
  170.                occurrence_table[header_byte]++;
  171.              }
  172.        header_byte=0;
  173.        for (i=1;i<=255;i++)
  174.            if (occurrence_table[i]<occurrence_table[header_byte])
  175.               header_byte=i;
  176.        write_byte(header_byte);
  177.        beginning_of_data();
  178.        read_block();
  179.        while (size_remaining_to_read())
  180.              { rle3look_for_occurr(&frame_nb,&frame_size,&repetition_valid);
  181.                if (repetition_valid)
  182.                              /* Was there a repetition? */
  183.                   { read_array(frame,frame_size);
  184.                     rle3write_rep(header_byte,frame,frame_nb);
  185.                   }
  186.                else          /* No pattern repetition */
  187.                     rle3write_non_rep(header_byte,read_byte());
  188.                fill_block(); /* All new analysis must start at 0 in the buffer */
  189.              }
  190.      }
  191. }
  192.  
  193. void help()
  194. /* Returned parameters: None
  195.    Action: Displays the help of the program and then stops its running
  196.    Errors: None
  197. */
  198. { printf("This utility enables you to compress a file by using RLE type 3 method\n");
  199.   printf("as given in 'La Video et Les Imprimantes sur PC'\n");
  200.   printf("\nUse: codrle3 source target\n");
  201.   printf("source: Name of the file to compress\n");
  202.   printf("target: Name of the compressed file\n");
  203. }
  204.  
  205. int main(argc,argv)
  206. /* Returned parameters: Return an error code (0=None)
  207.    Action: Main procedure
  208.    Errors: Detected, handled and an error code is returned, if any
  209. */
  210. int argc;
  211. char *argv[];
  212. { if (argc!=3)
  213.      { help();
  214.        exit(BAD_ARGUMENT);
  215.      }
  216.   else if ((source_file=fopen(argv[1],"rb"))==NULL)
  217.           { help();
  218.             exit(BAD_FILE_NAME);
  219.           }
  220.        else if ((dest_file=fopen(argv[2],"wb"))==NULL)
  221.                { help();
  222.                  exit(BAD_FILE_NAME);
  223.                }
  224.             else { rle3encoding();
  225.                    fclose(source_file);
  226.                    fclose(dest_file);
  227.                  }
  228.   printf("Execution of codrle3 completed.\n");
  229.   return (NO_ERROR);
  230. }
  231.